package controllers

import (
	"webx/models"
	"webx/services"
	"webx/utils"

	"github.com/gin-gonic/gin"
)

type UserController struct {
	userService *services.UserService
}

func NewUserController(userService *services.UserService) *UserController {
	return &UserController{userService: userService}
}

// GetUserByID godoc
// @Summary Get user by ID
// @Description Get user details by user ID
// @Tags users
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} utils.Response{data=models.User}
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /users/{id} [get]
func (c *UserController) GetUserByID(ctx *gin.Context) {
	id, err := utils.GetUintParam(ctx, "id")
	if err != nil {
		utils.Fail(ctx, 400, "Invalid user ID")
		return
	}

	user, err := c.userService.GetUserByID(id)
	if err != nil {
		utils.Fail(ctx, 404, err.Error())
		return
	}

	utils.Success(ctx, user)
}

// CreateUser godoc
// @Summary Create a new user
// @Description Create a new user with the input payload
// @Tags users
// @Accept json
// @Produce json
// @Param user body models.User true "Create user"
// @Success 201 {object} utils.Response{data=models.User}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /users [post]
func (c *UserController) CreateUser(ctx *gin.Context) {
	var user models.User
	if err := ctx.ShouldBindJSON(&user); err != nil {
		utils.Fail(ctx, 400, err.Error())
		return
	}

	if err := c.userService.CreateUser(&user); err != nil {
		utils.Fail(ctx, 500, err.Error())
		return
	}

	utils.Success(ctx, user)
}

// UpdateUser godoc
// @Summary Update user
// @Description Update user with the input payload
// @Tags users
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Param user body models.User true "Update user"
// @Success 200 {object} utils.Response{data=models.User}
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /users/{id} [put]
func (c *UserController) UpdateUser(ctx *gin.Context) {
	id, err := utils.GetUintParam(ctx, "id")
	if err != nil {
		utils.Fail(ctx, 400, "Invalid user ID")
		return
	}

	var user models.User
	if err := ctx.ShouldBindJSON(&user); err != nil {
		utils.Fail(ctx, 400, err.Error())
		return
	}

	user.ID = id
	if err := c.userService.UpdateUser(&user); err != nil {
		utils.Fail(ctx, 500, err.Error())
		return
	}

	utils.Success(ctx, user)
}

// DeleteUser godoc
// @Summary Delete user
// @Description Delete user by ID
// @Tags users
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} utils.Response
// @Failure 400 {object} utils.Response
// @Failure 404 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /users/{id} [delete]
func (c *UserController) DeleteUser(ctx *gin.Context) {
	id, err := utils.GetUintParam(ctx, "id")
	if err != nil {
		utils.Fail(ctx, 400, "Invalid user ID")
		return
	}

	if err := c.userService.DeleteUser(id); err != nil {
		utils.Fail(ctx, 500, err.Error())
		return
	}

	utils.Success(ctx, nil)
}

// ListUsers godoc
// @Summary List users
// @Description Get a list of users with pagination
// @Tags users
// @Accept json
// @Produce json
// @Param page query int false "Page number" default(1)
// @Param page_size query int false "Page size" default(10)
// @Success 200 {object} utils.Response{data=[]models.User}
// @Failure 400 {object} utils.Response
// @Failure 500 {object} utils.Response
// @Router /users [get]
func (c *UserController) ListUsers(ctx *gin.Context) {
	page, pageSize := utils.GetPaginationParams(ctx)

	users, total, err := c.userService.ListUsers(page, pageSize)
	if err != nil {
		utils.Fail(ctx, 500, err.Error())
		return
	}

	response := gin.H{
		"items": users,
		"total": total,
		"page":  page,
		"size":  pageSize,
	}

	utils.Success(ctx, response)
}
